package com.pool.socket.DataType;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.pool.socket.SocketServer;

public class MessageFormat {

	public static ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;
	public static int packetHeaderLen = 16;

	public static int byteArrayToPacketLen(byte[] data) {
		ByteBuffer bb = ByteBuffer.wrap(data);
		bb.order(byteOrder);
		byte[] tmp = new byte[6];
		bb.get(tmp, 0, 6);
		if ((tmp[0] != Byte.valueOf("00", 16))
				|| (tmp[1] != Byte.valueOf("43", 16))
				|| (tmp[2] != Byte.valueOf("45", 16))
				|| (tmp[3] != Byte.valueOf("54", 16))
				|| (tmp[4] != Byte.valueOf("43", 16))
				|| (tmp[5] != Byte.valueOf("00", 16))) {
			System.out.println(tmp[0] + "," + tmp[1] + "," + tmp[2] + ","
					+ tmp[3] + "," + tmp[4] + "," + tmp[5]);
			System.exit(0);
			return -1;
		}
		bb.getInt();
		bb.getInt();
		short len = bb.getShort();
		return len;
	}

	static public boolean isRequestConfirm(byte[] data) {
		ByteBuffer bb = ByteBuffer.wrap(data);
		bb.order(byteOrder);
		byte[] tmp = new byte[6];
		bb.get(tmp, 0, 6);
		if ((tmp[0] != Byte.valueOf("00", 16))
				|| (tmp[1] != Byte.valueOf("43", 16))
				|| (tmp[2] != Byte.valueOf("45", 16))
				|| (tmp[3] != Byte.valueOf("54", 16))
				|| (tmp[4] != Byte.valueOf("43", 16))
				|| (tmp[5] != Byte.valueOf("00", 16))) {
			return false;
		}
		bb.get(tmp, 0, 4);
		if ((tmp[2] != Byte.valueOf("00", 16))
				|| (tmp[3] != Byte.valueOf("02", 16))) {
			return false;
		}
		return true;

	}

	static public boolean isAddressList(byte[] data) {
		ByteBuffer bb = ByteBuffer.wrap(data);
		bb.order(byteOrder);
		byte[] tmp = new byte[6];
		bb.get(tmp, 0, 6);
		if ((tmp[0] != Byte.valueOf("00", 16))
				|| (tmp[1] != Byte.valueOf("43", 16))
				|| (tmp[2] != Byte.valueOf("45", 16))
				|| (tmp[3] != Byte.valueOf("54", 16))
				|| (tmp[4] != Byte.valueOf("43", 16))
				|| (tmp[5] != Byte.valueOf("00", 16))) {
			return false;
		}
		bb.get(tmp, 0, 4);
		if ((tmp[2] != Byte.valueOf("00", 16))
				|| (tmp[3] != Byte.valueOf("03", 16))) {
			return false;
		}
		return true;

	}

	static public boolean isIntervalSetConfirm(byte[] data) {
		ByteBuffer bb = ByteBuffer.wrap(data);
		bb.order(byteOrder);
		byte[] tmp = new byte[6];
		bb.get(tmp, 0, 6);
		if ((tmp[0] != Byte.valueOf("00", 16))
				|| (tmp[1] != Byte.valueOf("43", 16))
				|| (tmp[2] != Byte.valueOf("45", 16))
				|| (tmp[3] != Byte.valueOf("54", 16))
				|| (tmp[4] != Byte.valueOf("43", 16))
				|| (tmp[5] != Byte.valueOf("00", 16))) {
			return false;
		}
		bb.get(tmp, 0, 4);
		if ((tmp[2] != Byte.valueOf("00", 16))
				|| (tmp[3] != Byte.valueOf("04", 16))) {
			return false;
		}
		return true;
	}

	static public boolean isHeartBeatMessage(byte[] data) {
		ByteBuffer bb = ByteBuffer.wrap(data);
		bb.order(byteOrder);
		byte[] tmp = new byte[6];
		bb.get(tmp, 0, 6);
		if ((tmp[0] != Byte.valueOf("00", 16))
				|| (tmp[1] != Byte.valueOf("43", 16))
				|| (tmp[2] != Byte.valueOf("45", 16))
				|| (tmp[3] != Byte.valueOf("54", 16))
				|| (tmp[4] != Byte.valueOf("43", 16))
				|| (tmp[5] != Byte.valueOf("00", 16))) {
			return false;
		}
		bb.get(tmp, 0, 4);
		if ((tmp[2] != Byte.valueOf("00", 16))
				|| (tmp[3] != Byte.valueOf("01", 16))) {
			return false;
		}
		bb.getInt();
		short len = bb.getShort();
		if (len != 2)
			return false;
		byte value = bb.get();
		if (value != Byte.valueOf("68", 16))
			return false;
		else
			return true;
	}

	static public boolean isSensorData(byte[] data) {
		ByteBuffer bb = ByteBuffer.wrap(data);
		bb.order(byteOrder);
		byte[] tmp = new byte[6];
		bb.get(tmp, 0, 6);
		if ((tmp[0] != Byte.valueOf("00", 16))
				|| (tmp[1] != Byte.valueOf("43", 16))
				|| (tmp[2] != Byte.valueOf("45", 16))
				|| (tmp[3] != Byte.valueOf("54", 16))
				|| (tmp[4] != Byte.valueOf("43", 16))
				|| (tmp[5] != Byte.valueOf("00", 16))) {
			return false;
		}
		bb.get(tmp, 0, 4);
		if ((tmp[2] != Byte.valueOf("00", 16))
				|| (tmp[3] != Byte.valueOf("0B", 16))) {
			return false;
		}
		return true;
	}

	private static int byteArrayToInt(byte[] b) { // message header should be 4
													// bytes
		final ByteBuffer bb = ByteBuffer.wrap(b);
		bb.order(byteOrder);
		return bb.getInt();
	}

	public static byte[] hexStringToByteArray(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.substring(2).toUpperCase();
		char[] hexChars = hexString.toCharArray();
		byte[] array = new byte[hexChars.length / 2];
		for (int i = 0; i < hexChars.length / 2; i++) {
			array[i] = (byte) (charToByte(hexChars[2 * i]) << 4 | charToByte(hexChars[2 * i + 1]));
		}
		return array;
	}

	public static byte hexStringToByte(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return 0;
		}
		hexString = hexString.substring(2).toUpperCase();
		char[] hexChars = hexString.toCharArray();
		byte d = (byte) (charToByte(hexChars[0]) << 4 | charToByte(hexChars[1]));
		return d;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}

	public static void initialize() {
		String path = System.getProperty("user.dir");
		ArrayList<String> fileNames = new ArrayList<String>();
		LinkedList<VirtualGateway> gateways = SocketServer.getGateways();
		fileNames.add(path + "/virtual-gateway/gateway1.xml");
		fileNames.add(path + "/virtual-gateway/gateway2.xml");
		// String xsdFilePath = System.getProperty("user.dir") + "/xml.xsd";
		try {
			JAXBContext jc = JAXBContext.newInstance(VirtualGateway.class);
			Unmarshaller unmarshaller = jc.createUnmarshaller();
			VirtualGateway gateway;
			for (String filePath : fileNames) {
				File xml = new File(filePath);
				// if (!this.isConfigFileValid(filePath, xsdFilePath))
				// return;
				gateway = (VirtualGateway) unmarshaller.unmarshal(xml);
				gateway.setFileName(filePath);
				gateways.add(gateway);
				System.out.println("UUID = " + UUID.randomUUID().toString());

			}
		} catch (JAXBException e) {
			e.printStackTrace();
		}

		for (int i = 0; i < gateways.size(); i++) {
			VirtualGateway gateway = gateways.get(i);
			UUID gatewayuuid = gateway.getGatewayUUID();
			int gatewayid = gateway.getGatewayID();
			Gson gson = new Gson();
			JsonObject jsonObj = new JsonObject();
			jsonObj.addProperty("GatewayId", gatewayid);
			jsonObj.addProperty("SensorId", 0);
			String jsonStr = gson.toJson(jsonObj);
			SocketServer.GlobalToLocalId.put(gatewayuuid, jsonStr);
			SocketServer.LocalIdToGlobal.put(jsonStr, gatewayuuid);

			List<Sensor> sensors = gateway.getSensors();
			System.out.println("This gateway have " + sensors.size()
					+ " sensors!");
			for (int j = 0; j < sensors.size(); j++) {
				Sensor sensor = sensors.get(j);
				JsonObject json = new JsonObject();
				UUID sensoruuid = sensor.getSensorUUID();
				json.addProperty("GatewayId", gatewayid);
				json.addProperty("SensorId", sensor.getSensorId());
				jsonStr = gson.toJson(json);
				System.out.println("200, jsonStr = " + jsonStr);
				SocketServer.GlobalToLocalId.put(sensoruuid, jsonStr);
				SocketServer.LocalIdToGlobal.put(jsonStr, sensoruuid);
				System.out.println("SensorUUID = " + sensoruuid.toString());
			}
		}

	}

}
